// models/SysRoleDept.js
const mongoose = require("mongoose");
const { Schema } = mongoose;

/**
 * 角色和部门关联表 - 对应 MySQL sys_role_dept 表
 * 多对多关系，使用复合主键
 */
const sysRoleDeptSchema = new Schema(
  {
    // 角色ID - 对应MySQL的role_id
    roleId: {
      type: Number,
      required: [true, "角色ID不能为空"],
      index: true,
      comment: "角色ID",
    },

    // 部门ID - 对应MySQL的dept_id
    deptId: {
      type: Number,
      required: [true, "部门ID不能为空"],
      index: true,
      comment: "部门ID",
    },

    // 创建时间 - MongoDB扩展字段，便于查询和管理
    createTime: {
      type: Date,
      default: Date.now,
      comment: "创建时间",
    },

    // 创建者 - MongoDB扩展字段
    createBy: {
      type: String,
      default: "",
      comment: "创建者",
    },
  },
  {
    // Schema 选项
    timestamps: false,
    collection: "sys_role_depts",
  }
);

// 创建复合唯一索引，模拟MySQL的复合主键
sysRoleDeptSchema.index({ roleId: 1, deptId: 1 }, { unique: true });

// 创建反向索引，便于双向查询
sysRoleDeptSchema.index({ deptId: 1, roleId: 1 });

// 虚拟字段 - 角色信息（需要populate）
sysRoleDeptSchema.virtual("role", {
  ref: "SysRole",
  localField: "roleId",
  foreignField: "roleId",
  justOne: true,
});

// 虚拟字段 - 部门信息（需要populate）
sysRoleDeptSchema.virtual("dept", {
  ref: "SysDept",
  localField: "deptId",
  foreignField: "deptId",
  justOne: true,
});

// 实例方法
sysRoleDeptSchema.methods = {
  // 获取关联信息（包含角色和部门详情）
  toDetailJSON: async function () {
    await this.populate("role", "roleName roleKey dataScope status");
    await this.populate("dept", "deptName parentId ancestors status");

    return {
      roleId: this.roleId,
      deptId: this.deptId,
      role: this.role
        ? {
            roleName: this.role.roleName,
            roleKey: this.role.roleKey,
            dataScope: this.role.dataScope,
            status: this.role.status,
          }
        : null,
      dept: this.dept
        ? {
            deptName: this.dept.deptName,
            parentId: this.dept.parentId,
            ancestors: this.dept.ancestors,
            status: this.dept.status,
          }
        : null,
      createTime: this.createTime,
      createBy: this.createBy,
    };
  },
};

// 静态方法
sysRoleDeptSchema.statics = {
  /**
   * 为角色分配数据权限部门
   */
  assignDeptsToRole: function (roleId, deptIds, createBy = "") {
    // 先删除角色的所有现有部门权限
    return this.deleteRoleDepts(roleId).then(() => {
      // 批量插入新的部门权限关联
      const roleDepts = deptIds.map((deptId) => ({
        roleId: roleId,
        deptId: deptId,
        createBy: createBy,
        createTime: new Date(),
      }));

      return this.insertMany(roleDepts);
    });
  },

  /**
   * 为部门分配角色
   */
  assignRolesToDept: function (deptId, roleIds, createBy = "") {
    // 先删除部门的所有现有角色关联
    return this.deleteDeptRoles(deptId).then(() => {
      // 批量插入新的角色关联
      const roleDepts = roleIds.map((roleId) => ({
        roleId: roleId,
        deptId: deptId,
        createBy: createBy,
        createTime: new Date(),
      }));

      return this.insertMany(roleDepts);
    });
  },

  /**
   * 删除角色的所有部门权限
   */
  deleteRoleDepts: function (roleId) {
    return this.deleteMany({ roleId: roleId });
  },

  /**
   * 删除部门的所有角色关联
   */
  deleteDeptRoles: function (deptId) {
    return this.deleteMany({ deptId: deptId });
  },

  /**
   * 删除特定的角色部门关联
   */
  deleteRoleDept: function (roleId, deptId) {
    return this.deleteOne({ roleId: roleId, deptId: deptId });
  },

  /**
   * 检查角色是否拥有某个部门权限
   */
  hasRoleDept: function (roleId, deptId) {
    return this.findOne({ roleId: roleId, deptId: deptId });
  },

  /**
   * 获取角色的所有部门ID
   */
  getRoleDeptIds: function (roleId) {
    return this.find({ roleId: roleId })
      .select("deptId -_id")
      .then((depts) => depts.map((dept) => dept.deptId));
  },

  /**
   * 获取角色的所有部门信息
   */
  getRoleDepts: function (roleId, options = {}) {
    const { includeDisabled = false } = options;

    let query = { roleId: roleId };

    return this.find(query)
      .populate({
        path: "dept",
        match: {
          ...(!includeDisabled && { status: "0" }),
        },
        select: "deptId deptName parentId ancestors orderNum status",
      })
      .then((roleDepts) =>
        roleDepts
          .filter((roleDept) => roleDept.dept !== null) // 过滤掉被populate条件排除的部门
          .map((roleDept) => roleDept.dept)
      );
  },

  /**
   * 获取角色的部门树
   */
  getRoleDeptTree: async function (roleId, options = {}) {
    const SysDept = mongoose.model("SysDept");
    const deptIds = await this.getRoleDeptIds(roleId);

    const { includeDisabled = false } = options;

    const query = {
      deptId: { $in: deptIds },
    };

    if (!includeDisabled) {
      query.status = "0";
    }

    const depts = await SysDept.find(query).sort({ parentId: 1, orderNum: 1 });

    return SysDept.buildDeptTree(depts);
  },

  /**
   * 获取部门的所有角色ID
   */
  getDeptRoleIds: function (deptId) {
    return this.find({ deptId: deptId })
      .select("roleId -_id")
      .then((roles) => roles.map((role) => role.roleId));
  },

  /**
   * 获取部门的所有角色信息
   */
  getDeptRoles: function (deptId) {
    return this.find({ deptId: deptId })
      .populate("role", "roleId roleName roleKey dataScope status")
      .then((roles) => roles.map((role) => role.role));
  },

  /**
   * 批量获取角色的部门信息
   */
  getRolesDepts: function (roleIds) {
    return this.find({ roleId: { $in: roleIds } })
      .populate("dept", "deptId deptName parentId ancestors status")
      .then((relations) => {
        const result = {};
        relations.forEach((relation) => {
          if (!result[relation.roleId]) {
            result[relation.roleId] = [];
          }
          result[relation.roleId].push(relation.dept);
        });
        return result;
      });
  },

  /**
   * 批量获取部门的角色信息
   */
  getDeptsRoles: function (deptIds) {
    return this.find({ deptId: { $in: deptIds } })
      .populate("role", "roleId roleName roleKey dataScope status")
      .then((relations) => {
        const result = {};
        relations.forEach((relation) => {
          if (!result[relation.deptId]) {
            result[relation.deptId] = [];
          }
          result[relation.deptId].push(relation.role);
        });
        return result;
      });
  },

  /**
   * 分页查询角色部门关联
   */
  findRoleDeptsPaginated: function (options = {}) {
    const { page = 1, limit = 10, roleId = null, deptId = null } = options;

    const skip = (page - 1) * limit;
    const query = {};

    if (roleId) {
      query.roleId = roleId;
    }

    if (deptId) {
      query.deptId = deptId;
    }

    return Promise.all([
      this.find(query)
        .populate("role", "roleName roleKey dataScope status")
        .populate("dept", "deptName parentId ancestors status")
        .skip(skip)
        .limit(limit)
        .sort({ createTime: -1 }),
      this.countDocuments(query),
    ]).then(([roleDepts, total]) => ({
      roleDepts: roleDepts.filter((rd) => rd.role && rd.dept), // 过滤掉无效的关联
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / limit),
      },
    }));
  },

  /**
   * 统计角色部门数量
   */
  getRoleDeptStats: function () {
    return this.aggregate([
      {
        $group: {
          _id: "$roleId",
          deptCount: { $sum: 1 },
        },
      },
      {
        $lookup: {
          from: "sys_roles",
          localField: "_id",
          foreignField: "roleId",
          as: "roleInfo",
        },
      },
      {
        $unwind: "$roleInfo",
      },
      {
        $group: {
          _id: null,
          totalRoles: { $sum: 1 },
          avgDeptsPerRole: { $avg: "$deptCount" },
          maxDeptsPerRole: { $max: "$deptCount" },
          minDeptsPerRole: { $min: "$deptCount" },
        },
      },
      {
        $project: {
          _id: 0,
          totalRoles: 1,
          avgDeptsPerRole: { $round: ["$avgDeptsPerRole", 2] },
          maxDeptsPerRole: 1,
          minDeptsPerRole: 1,
        },
      },
    ]);
  },

  /**
   * 统计部门角色数量
   */
  getDeptRoleStats: function () {
    return this.aggregate([
      {
        $group: {
          _id: "$deptId",
          roleCount: { $sum: 1 },
        },
      },
      {
        $lookup: {
          from: "sys_depts",
          localField: "_id",
          foreignField: "deptId",
          as: "deptInfo",
        },
      },
      {
        $unwind: "$deptInfo",
      },
      {
        $group: {
          _id: null,
          totalDepts: { $sum: 1 },
          avgRolesPerDept: { $avg: "$roleCount" },
          maxRolesPerDept: { $max: "$roleCount" },
          minRolesPerDept: { $min: "$roleCount" },
        },
      },
      {
        $project: {
          _id: 0,
          totalDepts: 1,
          avgRolesPerDept: { $round: ["$avgRolesPerDept", 2] },
          maxRolesPerDept: 1,
          minRolesPerDept: 1,
        },
      },
    ]);
  },

  /**
   * 获取部门数量最多的角色
   */
  getRolesWithMostDepts: function (limit = 10) {
    return this.aggregate([
      {
        $group: {
          _id: "$roleId",
          deptCount: { $sum: 1 },
        },
      },
      {
        $sort: { deptCount: -1 },
      },
      {
        $limit: limit,
      },
      {
        $lookup: {
          from: "sys_roles",
          localField: "_id",
          foreignField: "roleId",
          as: "roleInfo",
        },
      },
      {
        $unwind: "$roleInfo",
      },
      {
        $project: {
          roleId: "$_id",
          roleName: "$roleInfo.roleName",
          roleKey: "$roleInfo.roleKey",
          dataScope: "$roleInfo.dataScope",
          deptCount: 1,
          _id: 0,
        },
      },
    ]);
  },

  /**
   * 获取角色数量最多的部门
   */
  getDeptsWithMostRoles: function (limit = 10) {
    return this.aggregate([
      {
        $group: {
          _id: "$deptId",
          roleCount: { $sum: 1 },
        },
      },
      {
        $sort: { roleCount: -1 },
      },
      {
        $limit: limit,
      },
      {
        $lookup: {
          from: "sys_depts",
          localField: "_id",
          foreignField: "deptId",
          as: "deptInfo",
        },
      },
      {
        $unwind: "$deptInfo",
      },
      {
        $project: {
          deptId: "$_id",
          deptName: "$deptInfo.deptName",
          parentId: "$deptInfo.parentId",
          roleCount: 1,
          _id: 0,
        },
      },
    ]);
  },

  /**
   * 根据用户ID获取数据权限部门
   * 通过用户角色关联查询用户有数据权限的部门
   */
  getUserDataDepts: async function (userId) {
    const SysUserRole = mongoose.model("SysUserRole");

    // 获取用户的所有角色ID
    const roleIds = await SysUserRole.getUserRoleIds(userId);

    if (roleIds.length === 0) {
      return [];
    }

    // 获取这些角色的所有部门ID（去重）
    const deptIds = await this.find({ roleId: { $in: roleIds } }).distinct(
      "deptId"
    );

    if (deptIds.length === 0) {
      return [];
    }

    // 获取部门详情
    const SysDept = mongoose.model("SysDept");
    return SysDept.find({
      deptId: { $in: deptIds },
      status: "0",
    }).sort({ parentId: 1, orderNum: 1 });
  },

  /**
   * 根据用户ID获取数据权限部门树
   */
  getUserDataDeptTree: async function (userId) {
    const SysDept = mongoose.model("SysDept");
    const depts = await this.getUserDataDepts(userId);
    return SysDept.buildDeptTree(depts);
  },

  /**
   * 检查用户是否有某个部门的数据权限
   */
  hasUserDeptDataPermission: async function (userId, deptId) {
    const userDepts = await this.getUserDataDepts(userId);
    const userDeptIds = userDepts.map((dept) => dept.deptId);

    // 检查直接权限
    if (userDeptIds.includes(deptId)) {
      return true;
    }

    // 检查祖先权限（如果用户有上级部门的权限，则对下级部门也有权限）
    const SysDept = mongoose.model("SysDept");
    const dept = await SysDept.findByDeptId(deptId);

    if (dept && dept.ancestors) {
      for (const ancestorId of dept.ancestors) {
        if (userDeptIds.includes(ancestorId)) {
          return true;
        }
      }
    }

    return false;
  },

  /**
   * 根据角色数据范围获取用户的数据权限部门
   */
  getUserDataDeptsByScope: async function (userId) {
    const SysUserRole = mongoose.model("SysUserRole");
    const SysDept = mongoose.model("SysDept");

    // 获取用户的所有角色
    const userRoles = await SysUserRole.getUserRoles(userId);

    let allDeptIds = new Set();

    for (const role of userRoles) {
      if (role.status !== "0") continue;

      switch (role.dataScope) {
        case "1": // 全部数据权限
          // 返回所有部门
          const allDepts = await SysDept.find({ status: "0" });
          allDepts.forEach((dept) => allDeptIds.add(dept.deptId));
          break;

        case "2": // 自定数据权限
          // 获取角色自定义的部门
          const customDeptIds = await this.getRoleDeptIds(role.roleId);
          customDeptIds.forEach((deptId) => allDeptIds.add(deptId));
          break;

        case "3": // 本部门数据权限
          // 这里需要获取用户所属部门，需要用户部门关联表
          // 暂时返回空，实际使用时需要根据业务实现
          break;

        case "4": // 本部门及以下数据权限
          // 这里需要获取用户所属部门及其子部门
          // 暂时返回空，实际使用时需要根据业务实现
          break;
      }
    }

    const deptIds = Array.from(allDeptIds);

    if (deptIds.length === 0) {
      return [];
    }

    return SysDept.find({
      deptId: { $in: deptIds },
      status: "0",
    }).sort({ parentId: 1, orderNum: 1 });
  },
};

// 查询助手
sysRoleDeptSchema.query = {
  // 按角色ID筛选
  byRoleId: function (roleId) {
    return this.where("roleId").equals(roleId);
  },

  // 按部门ID筛选
  byDeptId: function (deptId) {
    return this.where("deptId").equals(deptId);
  },

  // 按创建时间范围筛选
  byCreateTimeRange: function (startDate, endDate) {
    return this.where("createTime").gte(startDate).lte(endDate);
  },
};

// 中间件
sysRoleDeptSchema.pre("save", async function (next) {
  // 验证角色和部门是否存在且状态正常
  try {
    const SysRole = mongoose.model("SysRole");
    const SysDept = mongoose.model("SysDept");

    const [role, dept] = await Promise.all([
      SysRole.findByRoleId(this.roleId),
      SysDept.findByDeptId(this.deptId),
    ]);

    if (!role) {
      return next(new Error(`角色ID ${this.roleId} 不存在`));
    }

    if (!dept) {
      return next(new Error(`部门ID ${this.deptId} 不存在`));
    }

    if (role.status !== "0") {
      return next(new Error(`角色 ${role.roleName} 已被禁用`));
    }

    if (dept.status !== "0") {
      return next(new Error(`部门 ${dept.deptName} 已被禁用`));
    }

    // 只有数据范围为"自定数据权限"的角色才能设置部门权限
    if (role.dataScope !== "2") {
      return next(
        new Error(`只有数据范围为"自定数据权限"的角色才能设置部门权限`)
      );
    }

    next();
  } catch (error) {
    next(error);
  }
});

// 创建模型
const SysRoleDept = mongoose.model("SysRoleDept", sysRoleDeptSchema);

module.exports = SysRoleDept;
